package org.dromara.apartment.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.dromara.apartment.domain.*;
import org.dromara.apartment.domain.bo.ApartmentInfoBo;
import org.dromara.apartment.domain.enums.ItemType;
import org.dromara.apartment.domain.vo.*;
import org.dromara.apartment.mapper.*;
import org.dromara.common.area.core.AreaHierarchy;
import org.dromara.common.area.core.utils.AreaUtils;
import org.dromara.common.core.exception.ServiceException;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.stereotype.Service;
import org.dromara.apartment.domain.bo.RoomInfoBo;
import org.dromara.apartment.service.IRoomInfoService;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Collection;
import java.util.stream.Collectors;

/**
 * 房间信息Service业务层处理
 *
 * @author ckj
 * @date 2025-06-24
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class RoomInfoServiceImpl implements IRoomInfoService {

    private final RoomInfoMapper baseMapper;
    private final GraphInfoMapper graphInfoMapper;
    private final RoomLabelMapper roomLabelMapper;
    private final RoomFacilityMapper roomFacilityMapper;
    private final RoomAttrValueMapper roomAttrValueMapper;
    private final RoomPaymentTypeMapper roomPaymentTypeMapper;
    private final ApartmentInfoMapper apartmentInfoMapper;
    private final AttrValueMapper attrValueMapper;
    private final FacilityInfoMapper facilityInfoMapper;
    private final LabelInfoMapper labelInfoMapper;
    private final PaymentTypeMapper paymentTypeMapper;

    /**
     * 查询房间信息
     *
     * @param id 主键
     * @return 房间信息
     */
    @Override
    public RoomInfoVo queryById(Long id){
        //1.查询房间信息
        RoomInfoVo roomInfoVo = baseMapper.selectVoById(id);
        if(ObjectUtil.isEmpty(roomInfoVo)){
            throw new ServiceException("房间不存在!");
        }
        //2.查询graphInfoList
        List<GraphInfoVo> graphVoList = graphInfoMapper.selectListByItemTypeAndId(ItemType.ROOM, id);
        //3.查询attrValueList
        List<AttrValueVo> attrvalueVoList = attrValueMapper.selectListByRoomId(id);
        //4.查询facilityInfoList
        List<FacilityInfoVo> facilityInfoList = facilityInfoMapper.selectListByRoomId(id);
        //5.查询labelInfoList
        List<LabelInfoVo> labelInfoList = labelInfoMapper.selectListByRoomId(id);
        //6.查询paymentTypeList
        List<PaymentTypeVo> paymentTypeList = paymentTypeMapper.selectListByRoomId(id);
        //7.组装结果
        if(CollUtil.isNotEmpty(graphVoList)){
            roomInfoVo.setGraphBoList(graphVoList.stream().map(GraphInfoVo::getName).collect(Collectors.joining()));
        }
        roomInfoVo.setAttrValueVoList(attrvalueVoList);
        roomInfoVo.setFacilityInfoList(facilityInfoList);
        roomInfoVo.setLabelInfoList(labelInfoList);
        roomInfoVo.setPaymentTypeVoList(paymentTypeList);
        return roomInfoVo;
    }

    /**
     * 分页查询房间信息列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 房间信息分页列表
     */
    @Override
    public TableDataInfo<RoomInfoVo> queryPageList(RoomInfoBo bo, PageQuery pageQuery) {
        Page<RoomInfoVo> result = baseMapper.selectVoPageList(pageQuery.build(), bo);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的房间信息列表
     *
     * @param bo 查询条件
     * @return 房间信息列表
     */
    @Override
    public List<RoomInfoVo> queryList(RoomInfoBo bo) {
        LambdaQueryWrapper<RoomInfo> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<RoomInfo> buildQueryWrapper(RoomInfoBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<RoomInfo> lqw = Wrappers.lambdaQuery();
        lqw.orderByAsc(RoomInfo::getId);
        lqw.eq(bo.getApartmentId() != null, RoomInfo::getApartmentId, bo.getApartmentId());
        lqw.eq(StringUtils.isNotBlank(bo.getRoomNumber()), RoomInfo::getRoomNumber, bo.getRoomNumber());
        lqw.like(StringUtils.isNotBlank(bo.getRoomName()), RoomInfo::getRoomName, bo.getRoomName());
        lqw.eq(bo.getRent() != null, RoomInfo::getRent, bo.getRent());
        lqw.eq(bo.getIsRelease() != null, RoomInfo::getIsRelease, bo.getIsRelease());
        return lqw;
    }

    /**
     * 新增房间信息
     *
     * @param bo 房间信息
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(RoomInfoBo bo) {
        RoomInfo add = MapstructUtils.convert(bo, RoomInfo.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
            setGraphInfo(add,bo.getGraphBoList());
            setAttrValue(add,bo.getAttrValueIds());
            setLabel(add,bo.getLabelInfoIds());
            setFacility(add,bo.getFacilityInfoIds());
            setPaymentType(add,bo.getPaymentTypeIds());
        }
        return flag;
    }

    /**
     * 修改房间信息
     *
     * @param bo 房间信息
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(RoomInfoBo bo) {
        RoomInfo update = MapstructUtils.convert(bo, RoomInfo.class);
        //如果是更新操作 先删除
        //1.删除图片列表
        LambdaQueryWrapper<GraphInfo> graphInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        graphInfoLambdaQueryWrapper.eq(GraphInfo::getItemType, ItemType.ROOM).
            eq(GraphInfo::getItemId,update.getId());
        graphInfoMapper.delete(graphInfoLambdaQueryWrapper);

        //2.删除属性信息列表
        LambdaQueryWrapper<RoomAttrValue> roomAttrValueLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roomAttrValueLambdaQueryWrapper.eq(RoomAttrValue::getRoomId,update.getId());
        roomAttrValueMapper.delete(roomAttrValueLambdaQueryWrapper);

        //3.删除配套信息表
        LambdaQueryWrapper<RoomFacility> roomFacilityLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roomFacilityLambdaQueryWrapper.eq(RoomFacility::getRoomId,update.getId());
        roomFacilityMapper.delete(roomFacilityLambdaQueryWrapper);

        //4.删除标签信息列表
        LambdaQueryWrapper<RoomLabel> roomLabelLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roomLabelLambdaQueryWrapper.eq(RoomLabel::getRoomId,update.getId());
        roomLabelMapper.delete(roomLabelLambdaQueryWrapper);

        //5.删除支付方式列表
        LambdaQueryWrapper<RoomPaymentType> roomPaymentTypeLambdaQueryWrapper = new LambdaQueryWrapper<>();
        roomPaymentTypeLambdaQueryWrapper.eq(RoomPaymentType::getRoomId,update.getId());
        roomPaymentTypeMapper.delete(roomPaymentTypeLambdaQueryWrapper);

        setGraphInfo(update,bo.getGraphBoList());
        setAttrValue(update,bo.getAttrValueIds());
        setLabel(update,bo.getLabelInfoIds());
        setFacility(update,bo.getFacilityInfoIds());
        setPaymentType(update,bo.getPaymentTypeIds());
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(RoomInfo entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除房间信息信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 校验并批量恢复房间信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean recoverWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (ids == null || ids.isEmpty()) {
            throw new ServiceException("恢复ID不能为空");
        }
        // 有效性校验
        if (Boolean.TRUE.equals(isValid)) {
            List<RoomInfo> records = baseMapper.selectDelFlagsByIds(ids);
            // 检查记录数是否匹配
            if (records.size() != ids.size()) {
                throw new ServiceException("部分记录不存在或已被删除");
            }
            // 检查是否全部为已删除状态
            boolean hasNotDeleted = records.stream()
                .anyMatch(item -> !item.getDelFlag());
            if (hasNotDeleted) {
                throw new ServiceException("存在非删除状态记录，无法恢复");
            }
        }
        // 执行恢复操作
        int updateCount = baseMapper.recoverByIds(ids, LoginHelper.getUserId());
        if (updateCount == 0) {
            throw new ServiceException("恢复失败，请检查记录状态");
        }
        return updateCount>0;
    }

    /**
     * 校验并批量永久删除房间信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean foreverDeleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (ids == null || ids.isEmpty()) {
            throw new ServiceException("恢复ID不能为空");
        }
        // 有效性校验
        if (Boolean.TRUE.equals(isValid)) {
            List<RoomInfo> records = baseMapper.selectDelFlagsByIds(ids);
            // 检查记录数是否匹配
            if (records.size() != ids.size()) {
                throw new ServiceException("部分记录不存在或已被删除");
            }
            // 检查是否全部为已删除状态
            boolean hasNotDeleted = records.stream()
                .anyMatch(item -> !item.getDelFlag());
            if (hasNotDeleted) {
                throw new ServiceException("存在非删除状态记录，无法永久删除");
            }
        }
        // 执行恢复操作
        int deleteCount = baseMapper.foreverDeleteByIds(ids);
        if (deleteCount == 0) {
            throw new ServiceException("永久删除失败，请检查记录状态");
        }
        return deleteCount>0;
    }

    /**
     * 修改状态
     *
     * @param bo 状态
     * @return 结果
     */
    @Override
    public int updateStatus(RoomInfoBo bo) {
        RoomInfoVo roomInfoVo=baseMapper.selectVoById(bo.getId());
        if(ObjectUtil.isEmpty(roomInfoVo)){
            throw new ServiceException("房间不存在");
        }
        return baseMapper.update(null,
            new LambdaUpdateWrapper<RoomInfo>()
                .set(ObjectUtil.isNotEmpty(bo.getIsUsed()),RoomInfo::getIsUsed, bo.getIsUsed())
                .set(ObjectUtil.isNotEmpty(bo.getIsRecommend()),RoomInfo::getIsRecommend, bo.getIsRecommend())
                .set(ObjectUtil.isNotEmpty(bo.getIsRelease()),RoomInfo::getIsRelease, bo.getIsRelease())
                .eq(RoomInfo::getId, bo.getId()));
    }

    /**
     * 查询最近7个超高性价比房间
     *
     * @return
     */
    @Override
    public List<RoomInfoVo> getCostEffectiveRooms() {
        List<RoomInfoVo> rooms = baseMapper.selectVoList(
            new LambdaQueryWrapper<RoomInfo>()
                .eq(RoomInfo::getDelFlag, false)
                .eq(RoomInfo::getIsRelease, true)
                .eq(RoomInfo::getIsUsed, false)
                .orderByAsc(RoomInfo::getRent)
                .orderByAsc(RoomInfo::getSort)
                .last("LIMIT 7")
        );
        rooms.stream().forEach(room -> {
            //3.查询attrValueList
            List<AttrValueVo> attrvalueVoList = attrValueMapper.selectListByRoomId(room.getId());
            //4.查询facilityInfoList
            List<FacilityInfoVo> facilityInfoList = facilityInfoMapper.selectListByRoomId(room.getId());
            //5.查询labelInfoList
            List<LabelInfoVo> labelInfoList = labelInfoMapper.selectListByRoomId(room.getId());
            //6.查询paymentTypeList
            List<PaymentTypeVo> paymentTypeList = paymentTypeMapper.selectListByRoomId(room.getId());
            room.setAttrValueVoList(attrvalueVoList);
            room.setFacilityInfoList(facilityInfoList);
            room.setLabelInfoList(labelInfoList);
            room.setPaymentTypeVoList(paymentTypeList);
        });
        return rooms;
    }

    /**
     * 查询5个推荐好房
     *
     * @return
     */
    @Override
    public List<RoomInfoVo> getRecommendRooms() {
        List<RoomInfoVo> rooms = baseMapper.selectVoList(
            new LambdaQueryWrapper<RoomInfo>()
                .eq(RoomInfo::getDelFlag, false)
                .eq(RoomInfo::getIsRelease, true)
                .eq(RoomInfo::getIsUsed, false)
                .eq(RoomInfo::getIsRecommend, true)
                .orderByAsc(RoomInfo::getSort)
                .last("LIMIT 5")
        );
        rooms.stream().forEach(room -> {
            //3.查询attrValueList
            List<AttrValueVo> attrvalueVoList = attrValueMapper.selectListByRoomId(room.getId());
            //4.查询facilityInfoList
            List<FacilityInfoVo> facilityInfoList = facilityInfoMapper.selectListByRoomId(room.getId());
            //5.查询labelInfoList
            List<LabelInfoVo> labelInfoList = labelInfoMapper.selectListByRoomId(room.getId());
            //6.查询paymentTypeList
            List<PaymentTypeVo> paymentTypeList = paymentTypeMapper.selectListByRoomId(room.getId());
            room.setAttrValueVoList(attrvalueVoList);
            room.setFacilityInfoList(facilityInfoList);
            room.setLabelInfoList(labelInfoList);
            room.setPaymentTypeVoList(paymentTypeList);
        });
        return rooms;
    }

    /**
     * 查询最近3个超高性价比房间
     *
     * @param apartmentId
     * @return
     */
    @Override
    public List<RoomInfoVo> getThreeCostEffectiveRooms(Long apartmentId) {
        List<RoomInfoVo> rooms = baseMapper.selectVoList(
            new LambdaQueryWrapper<RoomInfo>()
                .eq(RoomInfo::getDelFlag, false)
                .eq(RoomInfo::getIsRelease, true)
                .eq(RoomInfo::getApartmentId, apartmentId)
                .orderByAsc(RoomInfo::getRent)
                .orderByAsc(RoomInfo::getSort)
                .last("LIMIT 3")
        );
        rooms.stream().forEach(room -> {
            //3.查询attrValueList
            List<AttrValueVo> attrvalueVoList = attrValueMapper.selectListByRoomId(room.getId());
            //4.查询facilityInfoList
            List<FacilityInfoVo> facilityInfoList = facilityInfoMapper.selectListByRoomId(room.getId());
            //5.查询labelInfoList
            List<LabelInfoVo> labelInfoList = labelInfoMapper.selectListByRoomId(room.getId());
            //6.查询paymentTypeList
            List<PaymentTypeVo> paymentTypeList = paymentTypeMapper.selectListByRoomId(room.getId());
            room.setAttrValueVoList(attrvalueVoList);
            room.setFacilityInfoList(facilityInfoList);
            room.setLabelInfoList(labelInfoList);
            room.setPaymentTypeVoList(paymentTypeList);
        });
        return rooms;
    }

    /**
     * 插入图片信息
     * @param entity
     * @param graphInfos
     */
    private void setGraphInfo(RoomInfo entity,String graphInfos) {
        if (StrUtil.isNotBlank(graphInfos)){
            List<String> graphInfoBoList=StrUtil.split(graphInfos, ",");
            ArrayList<GraphInfo> graphInfoList = new ArrayList<>();
            for (String graphInfoId : graphInfoBoList) {
                GraphInfo graphInfo = new GraphInfo();
                graphInfo.setName(graphInfoId);
                graphInfo.setItemType(ItemType.ROOM.getType());
                graphInfo.setItemId(entity.getId());
                graphInfoList.add(graphInfo);
            }
            graphInfoMapper.insertBatch(graphInfoList);
        }
    }

    /**
     * 设置房间属性
     * @param entity
     * @param attrValueIds
     */
    private void setAttrValue(RoomInfo entity,List<Long> attrValueIds) {
        if (CollUtil.isNotEmpty(attrValueIds)){
            ArrayList<RoomAttrValue> roomAttrValuesList = new ArrayList<>();
            for (Long attrValueId : attrValueIds) {
                RoomAttrValue roomAttrValue = new RoomAttrValue();
                roomAttrValue.setRoomId(entity.getId());
                roomAttrValue.setAttrValueId(attrValueId);
                roomAttrValuesList.add(roomAttrValue);
            }
            roomAttrValueMapper.insertBatch(roomAttrValuesList);
        }
    }

    /**
     * 设置房间配套信息
     * @param entity
     * @param facilityInfoIds
     */
    private void setFacility(RoomInfo entity,List<Long> facilityInfoIds) {
        if (CollUtil.isNotEmpty(facilityInfoIds)){
            ArrayList<RoomFacility> roomFacilityList = new ArrayList<>();
            for (Long facilityInfoId : facilityInfoIds) {
                RoomFacility roomFacility = new RoomFacility();
                roomFacility.setRoomId(entity.getId());
                roomFacility.setFacilityId(facilityInfoId);
                roomFacilityList.add(roomFacility);
            }
            roomFacilityMapper.insertBatch(roomFacilityList);
        }
    }

    /**
     * 设置房间标签
     * @param entity
     * @param labelInfoIds
     */
    private void setLabel(RoomInfo entity,List<Long> labelInfoIds) {
        if (CollUtil.isNotEmpty(labelInfoIds)){
            ArrayList<RoomLabel> roomLabelList = new ArrayList<>();
            for (Long labelInfoId : labelInfoIds) {
                RoomLabel roomLabel = new RoomLabel();
                roomLabel.setRoomId(entity.getId());
                roomLabel.setLabelId(labelInfoId);
                roomLabelList.add(roomLabel);
            }
            roomLabelMapper.insertBatch(roomLabelList);
        }
    }

    /**
     * 设置房间支付方式
     * @param entity
     * @param paymentTypeIds
     */
    private void setPaymentType(RoomInfo entity,List<Long> paymentTypeIds) {
        if (CollUtil.isNotEmpty(paymentTypeIds)){
            ArrayList<RoomPaymentType> roomPaymentTypeList = new ArrayList<>();
            for (Long paymentTypeId : paymentTypeIds) {
                RoomPaymentType roomPaymentType = new RoomPaymentType();
                roomPaymentType.setRoomId(entity.getId());
                roomPaymentType.setPaymentTypeId(paymentTypeId);
                roomPaymentTypeList.add(roomPaymentType);
            }
            roomPaymentTypeMapper.insertBatch(roomPaymentTypeList);
        }
    }


}
